package com.acme.bankapp.service.bank;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.acme.bankapp.domain.bank.Account;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.ClientRegistrationListener;
import com.acme.bankapp.domain.bank.SavingsAccount;
import com.acme.bankapp.domain.bank.CheckingAccount;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.domain.bank.Gender;
import com.acme.bankapp.domain.bank.BankException;
import com.acme.bankapp.domain.bank.NotEnoughFundsException;

public class BankService {

	public static class PrintClientListener implements
			ClientRegistrationListener {
		public void onClientAdded(Client c) {
			System.out.print(c.getClientSalutation());
			for (Account account : c.getAccounts()) {
				System.out.print(": " + account.maximumAmountToWithdraw());
			}
			System.out.println("");
		}
	}

	public static class EmailNotificationListener implements
			ClientRegistrationListener {
		public void onClientAdded(Client c) {
			System.out.println("Notification email for client "
					+ c.getClientSalutation() + " to be sent");
		}
	}

	public static class DebugListener implements ClientRegistrationListener {
		public void onClientAdded(Client c) {
			Calendar calendar = Calendar.getInstance();
			SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
			System.out.println("Client " + c.getClientSalutation() + " "
					+ format.format(calendar.getTime()));
		}
	}

	public static Bank createBankWithListeners() {
		ClientRegistrationListener[] listeners = new ClientRegistrationListener[3];
		listeners[0] = new PrintClientListener();
		listeners[1] = new EmailNotificationListener();
		listeners[2] = new DebugListener();
		return new Bank(listeners);
	}

	static void addClient(Bank bank, Client client) {
		bank.addClient(client);
	}

	public static void generateClients(Bank bank, int number) {
		for (int i = 0; i < number; i++) {
			addClient(bank, generateClient());
		}
	}

	public static Client generateClient() {
		String[][] names = {
				{ "Andrey", "Ivan", "Gleb", "Vasiliy", "Oleg", "Stanislav" },
				{ "Diana", "Olga", "Alexandra", "Natalia", "Maria" } };

		Account newAccount = Math.random() < 0.5 ? new SavingsAccount(Math.random() * 100) : new CheckingAccount(Math.random() * 100, Math.random() * 100);
		Gender newGender = Math.random() < 0.5 ? Gender.MALE : Gender.FEMALE;
		String newName = names[newGender.ordinal()][((int) (Math.random() * 100))
				% names[newGender.ordinal()].length];

		Client newClient = new Client(newName, newGender, newAccount);
		return newClient;
	}

	static void modifyBank(Bank bank) throws BankException {
		for (Client client : bank.getClients()) {
			if (Math.random() < 0.5) {
				Set<Account> accounts = client.getAccounts();
				Iterator<Account> iterator = accounts.iterator();
				if (iterator.hasNext()) {
					Account account = iterator.next();
					double amount = Math.random() * 50;
					if (Math.random() < 0.5) {
						account.withdraw(amount);
					} else {
						account.deposit(amount);
					}
				}
			}
		}
	}

	static void printMaximumAmountToWithdraw(Bank bank) {
		System.out.println("List of clients:");
		for (Client client : bank.getClients()) {
			System.out.print(client.getClientSalutation());
			for (Account account : client.getAccounts()) {
				System.out.print(": " + account.maximumAmountToWithdraw());
			}
			System.out.println("");
		}
	}

	static void printClients(Bank bank) {
		System.out.println("List of clients:");
		StringBuffer sbuffer = new StringBuffer();
		for (Client client : bank.getClients()) {
			sbuffer.append(client + "\n");
		}
		System.out.println(sbuffer);
		System.out.println("");
	}

}
